perm filename 11FTP.SAI[11,HE]10 blob
sn#626803 filedate 1981-11-30 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00007 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 BEGIN "11FTP"
C00004 00003 ! Auxiliary routines: parse10, parse11, outbuf, inbuf
C00008 00004 ! Main program - initialization
C00012 00005 ! Command loop - Exit & Alias
C00015 00006 ! Store 11file ← 10file
C00020 00007 ! Get 10file ← 11file & Fin
C00025 ENDMK
C⊗;
BEGIN "11FTP"
DEFINE CRLF="('15&'12)",
CR ="'15",
LF ="'12",
FF ="'14",
! = "COMMENT ",
TIL="STEP 1 UNTIL";
REQUIRE "11UTIL.HDR[11,SYS]" SOURCE_FILE;
DEFINE TTYSET = "'047000400121";
DEFINE GETLIN = "'051300000000";
DEFINE GETPPN = "'047000000024";
DEFINE DSKPPN = "'047000400071";
INTEGER pn,proj; ! Who's running ftp?;
INTEGER aliaspn, aliasproj; ! Alias of runner;
INTEGER chan; ! Channel number for I/O to RSX;
INTEGER dskchan; ! Channel number for 10 disk I/O;
EXTERNAL INTEGER _SKIP_;
INTEGER ARRAY buffer[1:256];
INTEGER talk10,char,p,i,j,k,l,dum,command,brk,brk1;
INTEGER eof,base,bufadr,bufptr,warn,gotline,needprompt;
STRING f1,f2,s,q,com,ack,fdev11,fnam10,fnam11,fext10,fext11,fver11,ppn10,ppn11;
STRING alppn11,aldev11;
LABEL fin;
! Auxiliary routines: parse10, parse11, outbuf, inbuf;
PROCEDURE parse10 (STRING s);
BEGIN
fnam10 ← fext10 ← ppn10 ← NULL;
! WHILE s=" " ∧ s ≠ NULL DO dum ← LOP(s); ! Strip off leading blanks;
WHILE s≠"." ∧ s≠"[" ∧ s≠NULL DO fnam10 ← fnam10 & LOP(s); ! Build up file name;
WHILE s≠"[" ∧ s≠NULL DO fext10 ← fext10 & LOP(s); ! Build up file extension;
IF s="[" THEN ppn10 ← s; ! Set ppn if present;
END;
PROCEDURE parse11 (STRING s);
BEGIN
fdev11 ← aldev11;
ppn11 ← alppn11;
fnam11 ← fext11 ← NULL;
fver11 ← ";0"; ! Default version number - means most recent version;
! WHILE s=" " ∧ s ≠ NULL DO dum ← LOP(s); ! Strip off leading blanks;
IF s≠"[" ∧ (s[2 FOR 1]=":" ∨ s[3 FOR 1]=":" ∨ s[4 FOR 1]=":") THEN
BEGIN ! Set device name;
fdev11 ← LOP(s);
WHILE s≠":" DO fdev11 ← fdev11 & LOP(s);
fdev11 ← fdev11 & LOP(s);
END;
IF s="[" THEN ! Set ppn if present;
BEGIN
ppn11 ← NULL;
DO ppn11 ← ppn11 & LOP(s) UNTIL s="]" ∨ s=NULL; ! Build up ppn;
ppn11 ← ppn11 & LOP(s); ! Tack on final "]";
END;
WHILE s≠"." ∧ s≠";" ∧ s≠NULL DO fnam11 ← fnam11 & LOP(s); ! Build up file name;
WHILE s≠";" ∧ s≠NULL DO fext11 ← fext11 & LOP(s); ! Build up file extension;
IF s=";" THEN fver11 ← s; ! Set version number if present;
END;
PROCEDURE OUTBUF;
BEGIN
WHILE (bufadr←PEEK(bufptr))=0 DO CALL(0,"SLEEP"); ! Sleep for 1 tick;
IF bufadr LAND 1 THEN ! Something's wrong - abort;
BEGIN
IF talk10 THEN PRINT("Error while writing file"&crlf);
GO TO fin;
END;
bufadr ← bufadr + base;
IF j THEN POKE(bufptr+2,j); ! Tell 11 this is last block;
POKEARRAY(bufadr,256,buffer,0); ! Transfer the sector over;
! POKEARRAY(bufadr,256,buffer,TWRJ); ! Transfer the sector over;
POKE(bufptr,0); ! Tell 11 to empty buffer now;
i ← 1;
END;
PROCEDURE INBUF;
BEGIN
WHILE (bufadr←PEEK(bufptr))=0 DO CALL(0,"SLEEP"); ! Sleep for 1 tick;
IF bufadr LAND 1 THEN ! Something's wrong - abort;
BEGIN
IF talk10 THEN PRINT("Error while reading file"&crlf);
GO TO fin;
END;
bufadr ← bufadr + base;
PEEKARRAY(bufadr,256,buffer,0); ! Transfer the sector over to 10;
j ← PEEK(bufptr+2) DIV 2; ! Get first free word if last block;
POKE(bufptr,0); ! Tell 11 we're done with buffer;
i ← 1;
END;
! Main program - initialization;
SETBREAK(1,crlf,NULL,"INS");
SETBREAK(2,lf&ff,cr,"INS");
SETBREAK(3,"←~}↓αβ∧¬ελ∞∂⊂⊃∩∪∀∃⊗↔_→≠≤≥≡∨",NULL,"INS"); ! Conversions for 11;
SETBREAK(4,"~"&'137&'175,NULL,"INS"); ! Conversions from 11;
SETBREAK(5,"=←"," ","KINS"); ! Convert to uppercase;
aldev11 ← "AL:"; ! Standard aliasing;
QUICK_CODE
GETPPN '13,; ! Who's running us?;
HRLZM '13,PN; ! Find out Prog.name;
HLLZM '13,PROJ; ! Find out what project;
SETZ '13,; ! Now find out what they're aliased to;
DSKPPN '13,; ! Put aliased PPN in 13 (code=0 to find out alias);
HRLZM '13,ALIASPN; ! Get prog.name of alias;
HLLZM '13,ALIASPROJ; ! and prj;
END;
alppn11 ← IF pn = CVSIX("ARG") THEN "[1,10]"
ELSE IF pn = CVSIX(" RV") THEN
IF aliasproj=CVSIX("PRJ") THEN "[7,16]" ELSE "[5,10]"
ELSE IF pn = CVSIX("JJC") THEN "[5,5]"
ELSE IF pn = CVSIX(" OK") THEN "[5,6]"
ELSE IF pn = CVSIX("SHM") THEN "[3,12]"
ELSE "[200,200]";
IF pn=CVSIX(" RV") ∧ aliasproj=CVSIX("PRJ") THEN aldev11 ← "DK1:";
ALINIT(false); ! Assign the ELF, but don't care about ARM;
! See whether 10 or 11 is requesting the transfer;
talk10 ← -1;
CODE(GETLIN,talk10); ! talk10 now has terminal characteristics & line number;
talk10 ← IF (talk10 LAND '7777)='53 THEN FALSE ELSE TRUE;
IF talk10 THEN
BEGIN
PRINT(crlf & "10-11 FTP Program. Type ? for help.",crlf);
PRINT ("Default 11 PPN for you is ",aldev11,alppn11,crlf,crlf);
chan ← GETCHAN;
OPEN(chan,"TTY53",0,1,1,999,brk1,dum);
QUICK_CODE
LABEL XIT,SETUP;
HRRI '13,SETUP; ! Command list to initialize the tty;
HRLI '13,-3; ! Number of commands;
TTYSET '13,0; ! Do it;
JRST XIT;
SETUP:
! '072453000001; ! Set TTY EXIST;
! '040453000005; ! Set tty speed = 1200 baud;
'001453000004; ! Set (XON &) NO ECHO;
'002453010000; ! Set TTY NO ARROW?;
'023453000001; ! Set TTY GAG;
XIT: END;
OUT(chan,"RUN $11FTP"&crlf);
WHILE INPUT(chan,1) = NULL DO ; ! Ignore echo from RSX;
WHILE (s←INPUT(chan,1)) = NULL ∨ s=">" DO ;
base ← CVO(s) LSH 6; ! Get address of Partition Base;
! PRINT("Partition base = ",CVOS(base),crlf);
WHILE (s←INPUT(chan,1)) = NULL DO ;
bufptr ← CVO(s); ! Get address of buffer pointer;
! PRINT("Buffer pointer = ",CVOS(bufptr),crlf);
END
ELSE
BEGIN
base ← CVO(INCHWL) LSH 6; ! Get address of buffer pointer;
bufptr ← CVO(INCHWL); ! Get address of buffer pointer;
END;
bufptr ← base + bufptr;
dskchan ← GETCHAN;
OPEN(dskchan,"DSK",0,19,19,512,brk,eof);
! Command loop - Exit & Alias;
needprompt ← TRUE; ! Prompt needed flag;
WHILE TRUE DO ! Get a command & do what needs doing;
BEGIN
IF needprompt THEN PRINT("*");
warn ← 0;
com ← INCHSL(gotline); ! Read command;
IF gotline≠0 THEN ! If no line input yet;
BEGIN
CALL (1,"SLEEP"); ! Go to sleep for one sec;
needprompt ← FALSE; ! Don't prompt next time;
CONTINUE;
END;
needprompt ← TRUE; ! Prompt them next time around;
command ← LOP(com) LOR '40; ! command = x, q, e, d, g or s for now;
IF command = "x" ∨ command = "e" ∨ command = "q" ∨ command = "d" THEN
BEGIN
IF talk10 THEN OUT(chan,"E"&cr&cr); ! Tell 11 that we're done;
! IF talk10 THEN OUT(chan,"X"&cr&cr); ! Tell 11 that we're done;
WHILE (s←INPUT(chan,1)) = NULL ∨ s≠">" DO ; ! Wait for MCR prompt;
i ← WORDIN(chan); ! This should clear the buffer;
IF command = "d" THEN
BEGIN ! Now invoke DIAL;
CLRBUF;
PTOSTR(0,"DIAL TTY53"&crlf);
END;
CALL(0,"EXIT");
END;
f1 ← SCAN(com,5,i); ! Get first file name & convert it to upper case;
f2 ← SCAN(com,5,i); ! Get second file name & convert it to upper case;
IF command = "a" THEN
BEGIN ! Get device & UIC alias for 11;
parse11(f1); ! Info now in fdev11 & ppn11;
aldev11 ← fdev11;
alppn11 ← ppn11;
END
! Store 11file ← 10file;
ELSE IF command = "s" THEN
BEGIN ! Store 11file ← 10file;
IF talk10 THEN
BEGIN
PARSE11(f1);
PARSE10(f2);
IF fnam11 = NULL THEN fnam11 ← fnam10;
IF fext11 = NULL THEN fext11 ← fext10;
IF fnam10 = NULL THEN fnam10 ← fnam11;
IF fext10 = NULL THEN fext10 ← fext11;
END
ELSE PARSE10(f1);
LOOKUP(dskchan,fnam10 & fext10 & ppn10,i);
IF i THEN
BEGIN PRINT("ABORTED - Can't find:",fnam10,fext10,ppn10,crlf); GO TO fin END;
IF talk10 THEN
BEGIN ! Tell 11 name of file to create;
OUT(chan,"G " & fdev11 & ppn11 & fnam11 & fext11 & fver11 & cr);
WHILE INPUT(chan,1) = NULL DO ; ! Ignore echo;
WHILE (s←INPUT(chan,1)) = NULL DO ;
IF ¬EQU("OK",s) THEN
BEGIN PRINT("Aborted by 11 "&s&crlf); GO TO fin END;
END
ELSE PRINT("OK"&crlf);
eof ← FALSE;
i ← j ← 0;
s ← INPUT(dskchan,2); ! Read in the first line;
IF EQU(s[1 FOR 9],"COMMENT ⊗") THEN
BEGIN ! Skip over E directory page;
DO s ← INPUT(dskchan,2) ! Read in the next line;
UNTIL EQU(s[1 FOR 3],"C⊗;") ∨ eof;
IF eof THEN
BEGIN
IF talk10 THEN PRINT("Directory end not detected"&crlf);
s ← NULL;
END;
s ← INPUT(dskchan,2); ! Skip ff;
s ← INPUT(dskchan,2); ! Read in the first real line;
END;
DO BEGIN ! Start transferring characters to the 11;
q ← NULL;
WHILE s≠NULL DO
BEGIN ! Convert Stanford ASCII to standard ASCII;
q ← q & SCAN(s,3,char); ! Scan to next conversion;
IF char = 0 THEN ! nothing to do;
ELSE IF char = "~" THEN q ← q & '176
ELSE IF char = "}" THEN q ← q & '175
ELSE IF char = "_" THEN q ← q & '137
ELSE IF char = "←" THEN q ← q & ":=" ! Be nice here;
ELSE IF char = "≥" THEN q ← q & ">="
ELSE IF char = "≤" THEN q ← q & "<="
ELSE IF char = "≠" THEN q ← q & "<>"
ELSE IF char = "¬" THEN q ← q & " not "
ELSE IF char = "∧" THEN q ← q & " and "
ELSE IF char = "∨" THEN q ← q & " or "
ELSE BEGIN
IF warn=0 THEN PRINT("Nonstandard chars: ");
OUTCHR (char); PRINT(" ");
warn ← warn + 1; ! Count characters we omitted;
END;
END;
s ← q;
IF brk = ff THEN s ← s & ff;
IF (i←i+1) > 256 THEN OUTBUF;
buffer[i] ← LENGTH(s); ! How long is this record?;
WHILE s ≠ NULL DO ! Stick them in the buffer 2/wd;
BEGIN
IF (i←i+1) > 256 THEN OUTBUF;
buffer[i] ← LOP(s) + (LOP(s) LSH 8);
! buffer[i] ← (LOP(s) LSH 18) + (LOP(s) LSH 26) + LOP(s) + (LOP(s) LSH 8);
END;
s ← INPUT(dskchan,2); ! Read in the next line;
END UNTIL eof ∧ LENGTH(s)=0;
j ← 2*i; ! First free byte address;
FOR k ← i+1 TIL 256 DO buffer[k]←0; ! Clear out end of block;
OUTBUF; ! And send it over to the 11;
END
! Get 10file ← 11file & Fin;
ELSE IF command = "g" THEN
BEGIN ! Get 10file ← 11file;
PARSE10(f1);
PARSE11(f2);
IF fnam10 = NULL THEN fnam10 ← fnam11;
IF fext10 = NULL THEN fext10 ← fext11;
IF fnam11 = NULL THEN fnam11 ← fnam10;
IF fext11 = NULL THEN fext11 ← fext10;
LOOKUP(dskchan,fnam10 & fext10 & ppn10,i); ! Does file already exist?;
IF ¬i THEN ! File exists: ask for confirmation;
BEGIN
i ← i LAND '777777; ! Look at right half = error bits;
IF i≠0 THEN BEGIN
PRINT("ABORTED - Can't enter:",fnam10,fext10,ppn10,crlf); GO TO fin END;
IF i=0 THEN PRINT("File already exists: ",fnam10&fext10&ppn10," Replace? ");
DO
BEGIN
i := inchrw; ! Wait for them to type a char;
PRINT(CRLF);
IF i="N" ∨ i="n" THEN BEGIN PRINT("Aborted.",CRLF); GO TO FIN END;
IF i≠"Y" ∧ i≠"y" THEN PRINT(" Replace (y/n)? ");
END
UNTIL i="y" ∨ i="Y";
END;
CLOSE(dskchan); ! Close file we opened for input;
ENTER(dskchan,fnam10 & fext10 & ppn10,i); ! Now open file for output;
IF i THEN
BEGIN PRINT("ABORTED - Can't enter:",fnam10,fext10,ppn10,crlf); GO TO fin END;
IF talk10 THEN
BEGIN ! Tell 11 name of file to read;
OUT(chan,"S " & fdev11 & ppn11 & fnam11 & fext11 & fver11 & cr);
WHILE INPUT(chan,1) = NULL DO ; ! Ignore echo;
WHILE (s←INPUT(chan,1)) = NULL DO ;
IF ¬EQU("OK",s) THEN
BEGIN PRINT("Aborted by 11 "&s&crlf); GO TO fin END;
END
ELSE PRINT("OK"&crlf);
i ← 256;
j ← 0;
WHILE j=0 ∨ i<j DO ! Start transferring characters to the 10;
BEGIN
IF (i←i+1) > 256 THEN INBUF;
k ← buffer[i]; ! Get byte count;
s ← NULL;
FOR l ← 1 STEP 2 UNTIL k DO ! unpack them from the buffer 2/wd;
BEGIN
IF (i←i+1) > 256 THEN INBUF;
p ← POINT(8,buffer[i],27); ! 11 for 4/wd;
char ← LDB(p);
s ← s & ILDB(p) & char;
! q ← ILDB(p) & char;
! char ← ILDB(p);
! s ← s & q & ILDB(p) & char;
END;
IF k MOD 2 THEN s ← s[1 FOR k];
q ← NULL;
WHILE s≠NULL DO
BEGIN ! Convert standard ASCII to Stanford ASCII;
q ← q & SCAN(s,4,char); ! Scan to next conversion;
IF char = 0 THEN ! nothing to do;
ELSE IF char = '176 THEN q ← q & "~"
ELSE IF char = '175 THEN q ← q & "}"
ELSE IF char = '137 THEN q ← q & "_"
ELSE warn ← warn + 1; ! Count characters we omitted;
END;
s ← q;
IF EQU(s,ff) THEN OUT(dskchan,s)
ELSE OUT(dskchan,s & crlf); ! Write out the next line;
END;
END
ELSE IF command="?" THEN BEGIN "Help them out"
PRINT("G to get a file from the 11"&crlf);
PRINT("S to store a file on the 11"&crlf);
PRINT("A to set an alias device & UIC on the 11 {default= AL:",alppn11,"}"&crlf);
PRINT("X to exit" &crlf);
PRINT("D for DIAL" &crlf&crlf);
END
ELSE PRINT("Unknown command",crlf);
fin:
CLOSE(dskchan);
IF warn THEN
PRINT("*WARNING* - file contained: ",warn," nonstandard characters."&crlf);
END;
END "11FTP";